<template>
  <div class="column-control-table">
    <!-- 下拉列控制区域 -->
    <div v-if="showColumnControl" class="column-dropdown">
      <el-dropdown trigger="click" placement="bottom-end">
        <el-icon :size="20" class="column-icon">
          <Setting />
        </el-icon>
        <template #dropdown>
          <el-dropdown-menu class="column-dropdown-menu">
            <!-- 列选项容器（可滚动） -->
            <div class="column-options-container">
              <el-dropdown-item v-for="column in allColumns" :key="column.prop">
                <el-checkbox
                  :model-value="checkedColumns.includes(column.prop)"
                  @change="(val) => handleColumnCheck(val, column.prop)"
                  :disabled="column.disabled || column.fixed"
                  :label="column.label"
                >
                  {{ column.label }}
                  <el-tag v-if="column.disabled" size="small" type="info" effect="plain" class="fixed-tag">固定展示</el-tag>
                  <el-tag v-else-if="column.fixed" size="small" type="info" effect="plain" class="fixed-tag">固定展示</el-tag>
                </el-checkbox>
              </el-dropdown-item>
            </div>

            <!-- 全选选项（固定在底部） -->
            <el-dropdown-item divided class="check-all-item">
              <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange" :disabled="allFixedColumnsSelected">
                全选
              </el-checkbox>
            </el-dropdown-item>
          </el-dropdown-menu>
        </template>
      </el-dropdown>
    </div>

    <!-- 表格区域 -->
    <el-table
      ref="tableRef"
      :data="tableData"
      border
      style="width: 100%"
      :key="tableKey"
      v-bind="tableProps"
      @select="handleSelect"
      @select-all="handleSelectAll"
    >
      <!-- 选择列 -->
      <el-table-column type="selection" width="55" align="center" fixed="left" />

      <el-table-column
        v-for="column in showColumns"
        :key="column.prop"
        :prop="column.prop"
        :label="column.label"
        :width="column.width"
        :min-width="column.minWidth"
        :fixed="column.fixed || (column.prop === 'operation' ? 'right' : false)"
        :formatter="column.formatter || defaultFormatter"
        :align="column.align || column.props?.align || 'center'"
        :header-align="column.headerAlign || column.props?.headerAlign || 'center'"
        v-bind="column.props"
      >
        <template v-if="column.slot" #default="scope">
          <slot v-if="tableData.length > 0" :name="column.slot" v-bind="scope"></slot>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页区域 -->
    <div class="pagination-container">
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[10, 20, 30, 50]"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, withDefaults, nextTick } from 'vue';
import { Setting } from '@element-plus/icons-vue';

interface TableColumn {
  prop: string;
  label: string;
  width?: string | number;
  minWidth?: string | number;
  fixed?: boolean | 'left' | 'right';
  disabled?: boolean;
  slot?: string;
  props?: Record<string, any>;
  formatter?: (row: any, column: any, cellValue: any) => string;
  show?: boolean;
  align?: 'left' | 'center' | 'right';
  headerAlign?: 'left' | 'center' | 'right';
}

interface TableProps extends Record<string, any> {
  height?: string | number;
  maxHeight?: string | number;
  stripe?: boolean;
  size?: 'large' | 'default' | 'small';
  'row-key'?: string | ((row: any) => string);
}

interface Props {
  data: Record<string, any>[];
  columns: TableColumn[];
  showColumnControl?: boolean;
  showCheckAll?: boolean;
  useLocalStorage?: boolean;
  storageKey?: string;
  tableProps?: TableProps;
  total?: number;
  currentPage?: number;
  pageSize?: number;
}

const props = withDefaults(defineProps<Props>(), {
  data: () => [],
  columns: () => [],
  showColumnControl: true,
  showCheckAll: true,
  useLocalStorage: false,
  storageKey: 'tableColumnsConfig',
  tableProps: () => ({}),
  total: 0,
  currentPage: 1,
  pageSize: 10
});

const emit = defineEmits<{
  (e: 'columns-change', columns: string[]): void;
  (e: 'size-change', size: number): void;
  (e: 'current-change', page: number): void;
  (e: 'selection-change', selection: any[]): void;
}>();

// 响应式数据
const tableRef = ref();
const tableData = ref([...props.data]);
const allColumns = ref<TableColumn[]>(JSON.parse(JSON.stringify(props.columns)));
const tableKey = ref(0);
const checkedColumns = ref<string[]>(initializeCheckedColumns());
const checkAll = ref(false);
const isIndeterminate = ref(false);
const currentPage = ref(props.currentPage);
const pageSize = ref(props.pageSize);
const total = ref(props.total);
const selectedRows = ref<any[]>([]);

// 默认格式化函数，处理空值显示
const defaultFormatter = (row: any, column: any, cellValue: any) => {
  if (cellValue === null || cellValue === undefined || cellValue === '') {
    return '--';
  }
  return cellValue;
};

// 初始化选中列
function initializeCheckedColumns(): string[] {
  const defaultSelected = props.columns.filter((column) => column.show !== false && !column.disabled).map((column) => column.prop);

  return [...props.columns.filter((c) => c.disabled).map((c) => c.prop), ...defaultSelected];
}

// 计算属性
const fixedDisplayColumns = computed(() => allColumns.value.filter((c) => c.disabled).map((c) => c.prop));

const fixedColumns = computed(() => allColumns.value.filter((c) => c.fixed).map((c) => c.prop));

const allFixedColumnsSelected = computed(() => fixedDisplayColumns.value.length === allColumns.value.length);

const showColumns = computed(() => allColumns.value.filter((c) => checkedColumns.value.includes(c.prop)));

// 初始化本地存储
if (props.useLocalStorage) {
  const saved = localStorage.getItem(props.storageKey);
  if (saved) {
    try {
      const parsed = JSON.parse(saved);
      if (Array.isArray(parsed)) {
        checkedColumns.value = [
          ...fixedDisplayColumns.value,
          ...parsed.filter((prop) => !fixedDisplayColumns.value.includes(prop) && allColumns.value.some((c) => c.prop === prop))
        ];
      }
    } catch (e) {
      console.error('解析本地存储失败:', e);
    }
  }
}

// 监听器
watch(
  () => [...props.data],
  (newVal) => {
    tableData.value = newVal;
    // 数据更新后清空选中项
    nextTick(() => {
      tableRef.value?.clearSelection();
    });
  },
  { immediate: true }
);

watch(
  () => props.total,
  (newVal) => {
    total.value = newVal;
  }
);

watch(
  () => props.currentPage,
  (newVal) => {
    currentPage.value = newVal;
  }
);

watch(
  () => props.pageSize,
  (newVal) => {
    pageSize.value = newVal;
  }
);

watch(
  () => [...props.columns],
  (newVal: TableColumn[]) => {
    allColumns.value = JSON.parse(JSON.stringify(newVal));

    const newFixed = newVal.filter((c) => c.disabled).map((c) => c.prop);
    checkedColumns.value = [
      ...newFixed,
      ...checkedColumns.value.filter((prop) => !fixedDisplayColumns.value.includes(prop) && newVal.some((c) => c.prop === prop))
    ];
  },
  { deep: true }
);

watch(
  checkedColumns,
  (newVal) => {
    updateCheckAllState(newVal);

    if (props.useLocalStorage) {
      const toSave = newVal.filter((prop) => !fixedDisplayColumns.value.includes(prop));
      localStorage.setItem(props.storageKey, JSON.stringify(toSave));
    }

    emit('columns-change', newVal);
  },
  { immediate: true }
);

// 方法
function updateCheckAllState(columns: string[]) {
  const selectable = allColumns.value.filter((c) => !c.disabled).map((c) => c.prop);
  const selected = columns.filter((prop) => selectable.includes(prop));

  checkAll.value = selected.length === selectable.length;
  isIndeterminate.value = selected.length > 0 && selected.length < selectable.length;
}

function handleCheckAllChange(val: boolean) {
  const selectable = allColumns.value.filter((c) => !c.disabled && !c.fixed).map((c) => c.prop);

  checkedColumns.value = val ? [...new Set([...checkedColumns.value, ...selectable])] : [...fixedDisplayColumns.value];

  tableKey.value += 1;
}

function handleColumnCheck(checked: boolean, prop: string) {
  if (checked) {
    if (!checkedColumns.value.includes(prop)) {
      checkedColumns.value = [...checkedColumns.value, prop];
    }
  } else {
    checkedColumns.value = checkedColumns.value.filter((p) => p !== prop);
  }
  tableKey.value += 1;
}

function handleSizeChange(val: number) {
  pageSize.value = val;
  emit('size-change', val);
}

function handleCurrentChange(val: number) {
  currentPage.value = val;
  emit('current-change', val);
}

function handleSelect(selection: any[], row: any) {
  selectedRows.value = selection;
  emit('selection-change', selection);
}

function handleSelectAll(selection: any[]) {
  selectedRows.value = selection;
  emit('selection-change', selection);
}

// 暴露方法
defineExpose({
  getSelectedRows: () => selectedRows.value,
  clearSelection: () => {
    tableRef.value?.clearSelection();
    selectedRows.value = [];
  }
});
</script>

<style scoped>
.column-control-table {
  width: 100%;
  position: relative;
}

.column-dropdown {
  position: absolute;
  right: 10px;
  top: 10px;
  z-index: 10;
}

.column-icon {
  cursor: pointer;
  color: var(--el-color-primary);
  transition: all 0.3s;
}

.column-icon:hover {
  color: var(--el-color-primary-light-3);
}

.fixed-tag {
  margin-left: 6px;
  vertical-align: middle;
}

:deep(.el-dropdown-menu__item) {
  padding: 5px 15px;
}

:deep(.el-checkbox) {
  width: 100%;
}

:deep(.el-checkbox__label) {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.pagination-container {
  margin-top: 15px;
  display: flex;
  justify-content: flex-end;
}

/* 固定列样式 */
:deep(.el-table__fixed-right),
:deep(.el-table__fixed-left) {
  height: 100% !important;
  box-shadow: -5px 0 15px -5px rgba(0, 0, 0, 0.1);
}

/* 下拉菜单容器 */
.column-dropdown-menu {
  max-height: 400px;
  display: flex;
  flex-direction: column;
}

/* 列选项容器（可滚动区域） */
.column-options-container {
  overflow-y: auto;
  max-height: calc(400px - 60px);
}

/* 全选选项（固定在底部） */
.check-all-item {
  position: sticky;
  bottom: 0;
  background: white;
  z-index: 1;
  box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
}

/* 调整下拉项样式 */
:deep(.el-dropdown-menu__item) {
  padding: 8px 16px;
  white-space: nowrap;
}

/* 滚动条样式 */
.column-options-container::-webkit-scrollbar {
  width: 6px;
}

.column-options-container::-webkit-scrollbar-thumb {
  background-color: var(--el-color-primary-light-5);
  border-radius: 3px;
}

.column-options-container::-webkit-scrollbar-track {
  background-color: var(--el-fill-color-lighter);
}
</style>
